use std::sync::Arc;

use dashmap::DashMap;
use std::ops::Deref;

use crate::RespFrame;
#[derive(Debug,Clone)]
pub struct Backend(Arc<BackendInner>);


#[derive(Debug)]
pub struct BackendInner{
    pub map: DashMap<String,RespFrame>,
    pub hmap: DashMap<String,DashMap<String,RespFrame>>,
}

impl Deref for Backend{
    type Target = BackendInner;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
    
}

impl BackendInner {
    pub fn new() -> Self{
        BackendInner{
            map: DashMap::new(),
            hmap: DashMap::new(),
        }
    }
}

impl Default for Backend{
    fn default() -> Self {
        Backend(Arc::new(BackendInner::new()))
    }
}

impl Backend{
    pub fn new() -> Self{
        Backend::default()
    }
    pub fn get(&self, key: &str) -> Option<RespFrame>{
        self.map.get(key).map(|v| v.value().clone())
    }
    pub fn set(&self, key: String, value: RespFrame){
        self.map.insert(key, value);
    }
    pub fn hget(&self, key: &str, field: &str) -> Option<RespFrame>{
        self.hmap.get(key).and_then(|m| m.get(field).map(|v| v.value().clone()))
    }
    pub fn hset(&self, key: String, field: String, value: RespFrame){
        let entry = self.hmap.entry(key).or_insert_with(|| DashMap::new());
        entry.insert(field, value); 
    }
}